using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UI;

public class Abstract : MonoBehaviour
{
    public Tilemap map;
    public Button btn;
    private int boundX;
    private int boundY;
    private int sizeX;
    private int sizeY;
    private double c;
    private string filepath1;
    private string filepath2;
    private string filepath3;

    // Start is called before the first frame update
    void Start()
    {
        boundX = map.cellBounds.x;
        boundY = map.cellBounds.y;
        sizeX = map.cellBounds.size.x;
        sizeY = map.cellBounds.size.y;
        btn.onClick.AddListener(foo);
        c = 5;
        filepath1 = @"C:\Users\caomb\Desktop\实训\索引.txt";
        filepath2 = @"C:\Users\caomb\Desktop\实训\抽象.txt";
        filepath3 = @"C:\Users\caomb\Desktop\实训\代表点.txt";
    }

    void foo()
    {
        int[, ] arr = new int[sizeY, sizeX];   //-1不可达，0未划分，1已划分，2为代表点;
        for(int i = 0; i < sizeY; i++) {
            for(int j = 0; j < sizeX; j++) {
                if(map.HasTile(new Vector3Int(boundX+j, boundY+i, 0))) {
                    arr[i, j] = 0;
                } else {
                    arr[i, j] = -1;
                }
            }
        }
        ArrayList list = new ArrayList();
        ArrayList ids = new ArrayList();
        ArrayList areas = new ArrayList();
        Vector3Int rep = new Vector3Int(0, 0, 0);
        Vector3Int p = new Vector3Int(0, 0, 0);
        int x = 0, y = 0;
        bool flag = true;
        while(flag) {
            while(y < sizeY) {
                if(arr[y, x] == 0) {
                    rep = new Vector3Int(boundX+x, boundY+y, 0);
                    arr[y, x] = 2;
                    break;
                }
                x++;
                if(x == sizeX) {
                    y++;
                    x = 0;
                    if(y == sizeY) {
                        flag = false;
                    }
                }
            }
            if(!flag) {
                break;
            }
            list.Add(rep);
            for(int i = 0; i < sizeY; i++) {
                for(int j = 0; j < sizeX; j++) {
                    if(arr[i, j] != 0) {
                        continue;
                    }
                    p = new Vector3Int(boundX+j, boundY+i, 0);
                    if(HillCliming(p, rep, c)) {
                        arr[i, j] = 1;
                        int id = i * sizeX + j;
                        ids.Add(id);
                        int area = list.Count - 1;
                        areas.Add(area);
                    }
                }
            }
        }
        using(StreamWriter sw1 = new StreamWriter(filepath1, false)) {
            for(int i = 0; i < ids.Count; i++) {
                sw1.WriteLine(ids[i] + " " + areas[i]);
            }
        }
        using(StreamWriter sw2 = new StreamWriter(filepath2, false)) {
            for(int i = 0; i < sizeY; i++) {
                char[] tmp = new char[sizeX];
                for(int j = 0; j < sizeX; j++) {
                    if(arr[i, j] == -1) {
                        tmp[j] = '0';
                    } else if(arr[i, j] == 1) {
                        tmp[j] = '1';
                    } else if(arr[i, j] == 2) {
                        tmp[j] = '2';
                    } else {
                        tmp[j] = 'e';
                    }
                }
                sw2.WriteLine(tmp);
            }
        }
        using(StreamWriter sw3 = new StreamWriter(filepath3, false)) {
            Vector3Int tmp = new Vector3Int(0, 0, 0);
            for(int i = 0; i < list.Count; i++) {
                tmp = (Vector3Int)list[i];
                sw3.WriteLine(tmp.x + " " + tmp.y);
            }
        }
    }

    bool HillCliming(Vector3Int p, Vector3Int rep, double c) {
        double count = 0;
        while(p != rep) {
            ArrayList list = new ArrayList();
            Vector3Int next = p;
            double f = 999999;
            for(int i = -1; i <= 1; i++) {
                for(int j = -1; j <= 1; j++) {
                    Vector3Int tmp = new Vector3Int(p.x+i, p.y+j, 0);
                    if(map.HasTile(tmp)) {
                        list.Add(tmp);
                    }
                }
            }
            double g = 0, h = 0;
            int offsetX = Math.Abs(rep.x - p.x);
            int offsetY = Math.Abs(rep.y - p.y);
            double square = offsetX * offsetX + offsetY * offsetY;
            double current_h = Math.Pow(square, 0.5);
            for(int i = 0; i < list.Count; i++) {
                Vector3Int tmp = (Vector3Int)list[i];
                offsetX = Math.Abs(p.x - tmp.x);
                offsetY = Math.Abs(p.y - tmp.y);
                square = offsetX * offsetX + offsetY * offsetY;
                g = Math.Pow(square, 0.5);
                offsetX = Math.Abs(rep.x - tmp.x);
                offsetY = Math.Abs(rep.y - tmp.y);
                square = offsetX * offsetX + offsetY * offsetY;
                h = Math.Pow(square, 0.5);
                if(current_h > h && f > g + h) {
                    next = tmp;
                    f = g + h;
                }
            }
            if(p == next) {
                if(p != rep) {
                    return false;
                } else {
                    return true;
                }
            } else {
                offsetX = Math.Abs(p.x - next.x);
                offsetY = Math.Abs(p.y - next.y);
                square = offsetX * offsetX + offsetY * offsetY;
                g = Math.Pow(square, 0.5);
                count += g;
                p = next;
                if(count > c) {
                    return false;
                } else if(p == rep) {
                    return true;
                }
            }
        }
        return true;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
